package xxx;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
import java.net.Socket;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

public class BlockingClient {

	private Socket socket;
	
	public BlockingClient(String host, int port) throws IOException {
		socket = new Socket(host, port);
		System.out.println("Client: Connected " + socket);
	}
	
	public static void main(String[] args) throws IOException, InterruptedException {
		final int nThreads = 5;
		final int nClients = 10;
		final int nMessages = 10;
		ExecutorService threads = Executors.newFixedThreadPool(nThreads);
		try {
			for(int i = 0, n = nClients; i < n; i++) {
				final int i0 = i;
				final int n0 = n;
				threads.submit(new Runnable() {
					public void run() {
						try {
							BlockingClient client = new BlockingClient("localhost", 6667);
							try {
								for(int j = 0, m = nMessages; j < m; j++) {
									System.out.println(String.format("Client: Sending message %d/%d (client %d/%d)", j, m, i0, n0));
									System.out.println(
										String.format("Client: (%s) %s",
											Thread.currentThread().getName(),
											client.send(
												String.format("MSG: %d.%d", i0, j))));
								}
							} finally {
								client.disconnect();
							}
						} catch(IOException e) {
							e.printStackTrace();
						}
					}});		
			}
		} finally {
			try {
				threads.shutdown();
				while(!threads.awaitTermination(10, TimeUnit.SECONDS)) {}
			} finally {
				BlockingClient client = new BlockingClient("localhost", 6667);
				try {
					client.send("QUIT");
				} finally {
					client.disconnect();
				}	
			}
		}
	}
	
	public void disconnect() throws IOException {
		socket.close();
	}
	
	public String send(String line) throws IOException {
		DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
		dos.writeInt(line.length());
		dos.flush();
		Writer w = new OutputStreamWriter(socket.getOutputStream());
		w.write(line);
		w.flush();

		DataInputStream dis = new DataInputStream(socket.getInputStream());
		char[] chars = new char[dis.readInt()];
		Reader r = new InputStreamReader(socket.getInputStream());
		r.read(chars);
		return new String(chars);
	}
	
}
